package epibot.WebRobots;

import epibot.EstruturasBiologicas.Epitopo;
import epibot.EstruturasBiologicas.Proteina;
import epibot.robot.Proxy.GereciadorDoProxy;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

/*
 * http://tools.immuneepitope.org/analyze/html_mhcibinding20101027/mhc_binding.html
 *
 * Query to the IEDB with consensus algorithm
 *
 * This method allways generate results with 9mer epitops
 */
public class IEDB_consensus {

    public static Proteina processCalibragem(String sequencia, String allele, String epi_len,
            String codProteina, String nomeSite) throws IOException {
        String rline; // Represents a line of the result table
        int line_count = 1;

        Proteina p = new Proteina(codProteina, nomeSite, allele, epi_len, 0); // só para armazenar a proteina e os epítopos

        // get the boundary used in the form
        String boundary = FormUtility.getBoundary();
        // build the URL and POST
        URL url = new URL("http://tools.immuneepitope.org/analyze/cgi-bin/mhc_I_binding.py");
        //  URLConnection http = url.openConnection();

        URLConnection http;
        Proxy proxy = GereciadorDoProxy.getConexao();

        if (proxy == null) {
            //System.out.println("sem proxy");
            http = url.openConnection();
        } else {
            // System.out.println("com proxy");
            http = url.openConnection(proxy);
        }

        http.setDoOutput(true);
        // Specify that it is a multipart form
        http.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        OutputStream os = http.getOutputStream();
        /**
         * The form uses Ajax so some of the fields below were discovered by
         * monitoring the HTTP POST traffic using WireShark software
         */
        FormUtility form = new FormUtility(os, boundary);
        form.add("pred_tool", "mhci");
        form.add("version", "20130222");

        form.add("sequence_text", sequencia);
        form.add("sequence_format", "auto");

        //"IEDB recommended", "netmhcpan", "ann", "smmpmbec", "smm", "comblib_sidney2008"    
        form.add("method", "1");
        /*
         * The "added" field are not present in the initial page source. It
         * seems they are created by an ajax procedure
         */

        String a = "";

        if (allele.equals("H2-Kd") || allele.equals("H2-Kb") || allele.equals("H2-Kk")) {
            a = allele.replace("H2", "H-2");//"H-2-Kd");
            form.add("species", "mouse");

        }

        //value="HLA A*0102"
        if (allele.equals("HLA-A0201")
                || allele.equals("HLA-A1101")
                || allele.equals("HLA-B2705")
                || allele.equals("HLA-B3801")
                || allele.equals("HLA-B3901")
                || allele.equals("HLA-B3902")
                || allele.equals("HLA-B5101")
                || allele.equals("HLA-A0205")
                || allele.equals("HLA-A3101")
                || allele.equals("HLA-B2702")
                || allele.equals("HLA-B3501")
                || allele.equals("HLA-B3701")
                || allele.equals("HLA-B4403")
                || allele.equals("HLA-B5102")
                || allele.equals("HLA-B5103")
                || allele.equals("HLA-B5201")
                || allele.equals("HLA-B5801")
                || allele.equals("HLA-A2402")
                || allele.equals("HLA-A6801")
                || allele.equals("HLA-B0702")
                || allele.equals("HLA-B1402")
                || allele.equals("HLA-B1501")
                || allele.equals("HLA-B1510")
                || allele.equals("HLA-B2709")
                || allele.equals("HLA-B4001")
                || allele.equals("HLA-B4101")
                || allele.equals("HLA-B4402")
                || allele.equals("HLA-B4501")
                || allele.equals("HLA-B4701")
                || allele.equals("HLA-B4901")
                || allele.equals("HLA-B5001")
                || allele.equals("HLA-A0101")
                || allele.equals("HLA-A0202")
                || allele.equals("HLA-A0203")
                || allele.equals("HLA-A0206")
                || allele.equals("HLA-A0211")
                || allele.equals("HLA-A0212")
                || allele.equals("HLA-A0216")
                || allele.equals("HLA-A0219")
                || allele.equals("HLA-A0250")
                || allele.equals("HLA-A0301")
                || allele.equals("HLA-A2301")
                || allele.equals("HLA-A2403")
                || allele.equals("HLA-A2501")
                || allele.equals("HLA-A2601")
                || allele.equals("HLA-A2602")
                || allele.equals("HLA-A2603")
                || allele.equals("HLA-A2902")
                || allele.equals("HLA-A3001")
                || allele.equals("HLA-A3002")
                || allele.equals("HLA-A3201")
                || allele.equals("HLA-A3301")
                || allele.equals("HLA-A6802")
                || allele.equals("HLA-A6901")
                || allele.equals("HLA-A8001")
                || allele.equals("HLA-B0801")
                || allele.equals("HLA-B0802")
                || allele.equals("HLA-B0803")
                || allele.equals("HLA-B1502")
                || allele.equals("HLA-B1503")
                || allele.equals("HLA-B1509")
                || allele.equals("HLA-B1517")
                || allele.equals("HLA-B1801")
                || allele.equals("HLA-B2703")
                || allele.equals("HLA-B4002")
                || allele.equals("HLA-B4601")
                || allele.equals("HLA-B4801")
                || allele.equals("HLA-B5301")
                || allele.equals("HLA-B5401")
                || allele.equals("HLA-B5701")
                || allele.equals("HLA-B7301")) {
            //value="HLA A*0201"
            //a = "HLA-A*02:01";
            a = allele.replace("HLA-A", "HLA-A*");
            a = a.replace("HLA-B", "HLA-B*");

            // System.out.println(a);
            form.add("species", "human");
        }

        form.add("added_allele", a);
        form.add("added_length", epi_len);
        form.add("refset", "off");
        form.complete();

        // read the results an parse the table
        InputStream is = http.getInputStream();
        StringBuilder buffer = new StringBuilder();
        int ch;
        String row;
        String[] fields;
        /**
         * Discard the 2 initial lines
         */
        while (is.read() != '\n');
        while (is.read() != '\n');

        /**
         * Read the rows
         */
        while ((ch = is.read()) != -1) {
            buffer.setLength(0);
            do {
                buffer.append((char) ch);
                ch = is.read();
            } while ((ch != '\n') && (ch != -1));
            row = buffer.toString();

            //  System.out.println(row);
            fields = row.split("\t");
            if (fields.length > 7) {
                String epitopo = fields[5], posicao = fields[2], score = fields[7];

                //System.out.println(epitopo + "," + posicao + "," + score);
                p.addEpitopo(new Epitopo(epitopo, Integer.parseInt(posicao), Double.parseDouble(score), 0, p));

            }
        }
        is.close();

        //ordena os epitopos       
        if (!p.getListaDeEpitopos().isEmpty()) {
            ArrayList<Epitopo> q = IEDB_consensus.quick(p.getListaDeEpitopos(), 0, p.getListaDeEpitopos().size() - 1);

            int rank = 0;
            double scoreAnt = -1;

            for (int k = 0; k < q.size(); k++) {
                double score = q.get(k).getScoreAbsoluto();
                if (score != scoreAnt) {
                    rank++;
                    scoreAnt = score;
                }
                q.get(k).setRank(rank);
            }
            p.setListaDeEpitopos(q);
        }

        return p;

    }

    /**
     * fUNÇÃO DE ORDENAÇÃO
     *
     * @param lista
     * @param primeiro
     * @param ultimo
     * @return
     */
    private static ArrayList<Epitopo> quick(ArrayList<Epitopo> lista, int primeiro, int ultimo) {
        int baixo, alto, passa = 0;
        Epitopo temp;
        double separador_lista;
        baixo = primeiro;
        alto = ultimo;
        separador_lista = lista.get((primeiro + ultimo) / 2).getScoreAbsoluto();

        do {
            while (lista.get(baixo).getScoreAbsoluto() < separador_lista) {
                baixo++;
            }
            while (lista.get(alto).getScoreAbsoluto() > separador_lista) {
                alto--;
            }

            if (baixo <= alto) {
                temp = lista.get(baixo);
                lista.set(baixo++, lista.get(alto));
                lista.set(alto--, temp);
                passa++;
            }
        } while (baixo <= alto);
        if (primeiro < alto) {
            quick(lista, primeiro, alto);
        }
        if (baixo < ultimo) {
            quick(lista, baixo, ultimo);
        }

        return lista;
    }
}
